import { calcActionItemAuthState, deepCopy, verifyValue } from "@/core";
import { IActionResult, IParam } from "@/interface";
import Schema from 'async-validator';

/**
 * @description 加载数据
 * @export
 * @param {IParam} modelParam
 * @param {IParam} runtimeParam
 * @return {*}  {Promise<IActionResult>}
 */
export async function load(modelParam: IParam, runtimeParam: IParam): Promise<IActionResult> {
  const { viewParams, context, emit, ctrlService, loadAction, viewState, data, name, opts } = runtimeParam;
  Object.assign(opts, {viewParams: deepCopy(viewParams)});
  const tempContext: any = deepCopy(context);
  emit('ctrlEvent', {ctrlName: name, action: 'onBeforeLoad', data: opts});
  const response = await ctrlService?.get?.(loadAction, tempContext, opts);
  if (response?.status === 200 && response?.data) {
    Object.assign(runtimeParam, {
      formData: response.data,
      action: 'load',
    })
    onFormLoad(modelParam, runtimeParam);
    viewState.next({tag: name, action: 'load', data: data});
    emit('ctrlEvent', {ctrlName: name, action: 'load', data: data});
    return {ret: true, data: [data]}
  }
  return {ret: false, data: [data]}
}

/**
 * @description 表单值改变
 * @export
 * @param {IParam} modelParam 模型参数
 * @param {IParam} runtimeParam 运行时参数
 */
export function formItemValueChange(modelParam: IParam, runtimeParam: IParam) {
  const { data, formItemName, formItemValue } = runtimeParam;
  if (formItemName) {
    data[formItemName] = formItemValue;
    resetFormItem(modelParam, runtimeParam);
    formGroupLogics(modelParam, runtimeParam);
  }
}

export function resetFormItem(modelParam: IParam, runtimeParam: IParam) {
  const { resetFormItems } = modelParam;
  resetFormItems.forEach((formItem: IParam) => {
    if (Object.is(formItem.resetItemName, name)) {
      Object.assign(runtimeParam, {
        formItemName: formItem.resetItemName,
        formItemValue: null,
      })
      formItemValueChange(modelParam, runtimeParam);
      if (formItem.valueItemName) {
        Object.assign(runtimeParam, {
          formItemName: formItem.valueItemName,
          formItemValue: null,
        })
        formItemValueChange(modelParam, runtimeParam);
      }
    }
  })
}

/**
 * @description 重置表单数据
 * @export
 * @param {IParam} modelParam 模型参数
 * @param {IParam} runtimeParam 运行时参数
 */
export function resetFormData(modelParam: IParam, runtimeParam: IParam) {
  const { data } = runtimeParam;
  if (Object.keys(data).length > 0) {
    Object.keys(data).forEach((name: string) => {
      if (data.hasOwnProperty(name)) {
        data[name] = null;
      }
    });
  }
}

/**
 * @description 设置表单项是否启用
 * @export
 * @param {IParam} modelParam
 * @param {IParam} runtimeParam
 */
export function setFormEnableCond(modelParam: IParam, runtimeParam: IParam){
  const { data, detailsModel } = runtimeParam;
  Object.values(detailsModel).forEach((detail: any) => {
    if (Object.is(detail.detailType, 'FORMITEM')) {
      const formItem: IParam = detail;
      formItem.setEnableCond(data.srfuf);
    }
  });
}

/**
 * @description 计算按钮状态
 * @export
 * @param {IParam} modelParam
 * @param {IParam} runtimeParam
 */
export function computeButtonState(modelParam: IParam, runtimeParam: IParam) {
  const { data, actionModel, detailsModel, UIService } = runtimeParam;
  calcActionItemAuthState(data, actionModel, UIService);
  if (detailsModel && Object.keys(detailsModel).length > 0) {
    Object.keys(detailsModel).forEach((name: any) => {
      const model = detailsModel[name];
      if (model?.detailType == 'BUTTON' && model.uiaction?.tag) {
        // 更新detailsModel里的按钮的权限状态值
        if (actionModel[model.uiAction.tag].dataActionResult) {
          detailsModel[name].isPower = true;
          detailsModel[name].visible = true;
          detailsModel[name].disabled = false;
        } else {
          detailsModel[name].visible = actionModel[model.uiAction.tag].visible;
          detailsModel[name].disabled = actionModel[model.uiAction.tag].disabled;
          detailsModel[name].isPower = actionModel[model.uiAction.tag].dataActionResult === 1 ? true : false;
        }
      } else if (model?.detailType == 'GROUPPANEL' && model.uiActionGroup?.details?.length > 0) {
        // 更新分组面板界面行为组的权限状态值
        model.uiActionGroup.details.forEach((actionDetail: any) => {
          actionDetail.visible = actionModel[actionDetail.tag].visible;
          actionDetail.disabled = actionModel[actionDetail.tag].disabled;
        });
      }
    });
  }
}

/**
 * @description 表单动态逻辑
 * @export
 * @param {IParam} modelParam
 * @param {IParam} runtimeParam
 */
export function formGroupLogics(modelParam: IParam, runtimeParam: IParam) {
  const { logics } = modelParam;
  const { detailsModel, data, formItemName } = runtimeParam;
  logics.forEach((logic: IParam) => {
    const relatedNames = logic.relatedNames || [];
    if (Object.is(formItemName, '') || relatedNames.indexOf(formItemName) != -1) {
      const ret: boolean = verifyGroupLogic(data, logic);
      switch (logic.logicCat) {
        // 动态空输入，不满足则必填
        case 'ITEMBLANK':
          detailsModel[logic.name].required = !ret;
          break;
        // 动态启用，满足则启用
        case 'ITEMENABLE':
          detailsModel[logic.name].setDisabled(!ret);
          break;
        // 动态显示，满足则显示
        case 'PANELVISIBLE':
          detailsModel[logic.name].setVisible(ret);
          break;
      }
    }
  })
}

/**
 * @description 校验动态逻辑
 * @param {IParam} data 表单数据
 * @param {IParam} logic 动态逻辑
 * @return {*} 
 */
export function verifyGroupLogic(data: IParam, logic: IParam) {
  if (logic.logicType == 'GROUP' && logic.logics?.length > 0) {
    let result: boolean = true;
    if (logic.groupOP == 'AND') {
      const falseItem = logic.logics.find((childLogic: IParam)=> {
        return !verifyGroupLogic(data, childLogic);
      })
      result = falseItem ? false : true;
    } else if (logic.groupOP == 'OR') {
      const trueItem = logic.logics.find((childLogic: IParam)=> {
        return verifyGroupLogic(data, childLogic);
      })
      result = trueItem ? true : false;
    }
    // 是否取反
    return logic.notMode ? !result : result;
  } else if (logic.logicType == 'SINGLE') {
    return verifyValue(data[logic.name], logic.condOP, logic.value);
  }
  return false;
}

/**
 * @description 校验表单项
 * @export
 * @param {IParam} modelParam
 * @param {IParam} runtimeParam
 * @return {*}  {Promise<boolean>}
 */
export async function checkFormItem(modelParam: IParam, runtimeParam: IParam): Promise<boolean> {
  const { rules } = modelParam;
  const { data, formItemName } = runtimeParam;
  return new Promise((resolve, reject) => {
    if (!rules[formItemName]) {
      resolve(true);
    }
    const validator = new Schema({ [formItemName]: rules[formItemName] });
    validator
      .validate({ [formItemName]: data[formItemName] })
      .then(() => {
        resolve(true);
      })
      .catch(() => {
        resolve(false);
      });
  });
}

/**
 * @description 表单更新项
 * @export
 * @param {IParam} modelParam 
 * @param {IParam} runtimeParam
 */
export async function updateFormItems(modelParam: IParam, runtimeParam: IParam) {
  const { mode, updateDetails } = modelParam;
  const { viewParams, opts, context, ctrlService, data } = runtimeParam;
  if (mode) {
    const arg: IParam = Object.assign(opts, { viewParams: deepCopy(viewParams)});
    const tempContext: IParam = deepCopy(context);
    const response: IParam = await ctrlService.frontLogic(mode, tempContext, arg);
    if (response.status == 200 && response.data) {
      updateDetails.forEach((name: string) => {
        if (data.hasOwnProperty(name)) {
          Object.assign(data, { [name]: response.data[name] });
        }
      });
      Object.assign(runtimeParam, {
        formData: deepCopy(data),
        acrion: 'updateFormItems',
      });
      onFormLoad(modelParam, runtimeParam);
    }
  }
}

/**
 * @description 表单加载完成
 * @param {IParam} modelParam 
 * @param {string} runtimeParam 
 */
 export function onFormLoad(modelParam: IParam, runtimeParam: IParam) {
  const { appDeCodeName } = modelParam;
  const { formData, action, context } = runtimeParam;
  if (appDeCodeName) {
    if (Object.is(action, 'save') || Object.is(action, 'autoSave') || Object.is(action, 'submit')) {
      if (formData[appDeCodeName]) {
        Object.assign(context, { [appDeCodeName]: formData[appDeCodeName] });
      }
    }
  }
  fillForm(modelParam, runtimeParam);
  setFormEnableCond(modelParam, runtimeParam);
  computeButtonState(modelParam, runtimeParam);
  Object.assign(runtimeParam, { formItemName: ''});
  formGroupLogics(modelParam, runtimeParam);
}

/**
 * @description 填充表单
 * @param {IParam} modelParam 
 * @param {string} runtimeParam 
 */
export function fillForm(modelParam: IParam, runtimeParam: IParam) {
  const { formData, action, data } = runtimeParam;
  Object.keys(data).forEach((name: string) => {
    if (data.hasOwnProperty(name)) {
      data[name] = formData[name];
    }
  });
  switch (action) {
    case "load":
      // updateDefault();
      break;
    case "loadDraft":
      // createDefault();
      break;
  }
}
